package org.fizz.network;


/**
 * @Author Fizz Pu
 * @Date 2021/5/3 上午11:52
 * @Version 1.0
 * 失之毫厘，缪之千里！
 */

import com.alibaba.fastjson.JSON;
import okhttp3.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 单线程下使用, 使用定时任务
 */

public class CumtNetWorkClientImp implements CumtNetWorkClient {

    // 本机ipV4地址
    private String ipV4;

    // 本机ipV6地址
    private String ipV6;

    // mac地址
    private String macAddress;

    // 用户名称
    private String userName;

    // 密码
    private String passWord;

    // 运营商
    private OperatorName operatorName;

    // 内置okhttp请求框架
    private OkHttpClient httpClient = new OkHttpClient();

    // 内置userAccount后缀
    private static Map<OperatorName, String> userAccountSuffix = new HashMap<>();
    // 登录url
    private String loginUrl = "http://10.2.5.251:801/eportal/";

    // 登出url
    private String loginOut = "http://10.2.5.251:801/eportal/";

    static {
        userAccountSuffix.put(OperatorName.Unicom, "@unicom");
        userAccountSuffix.put(OperatorName.Telecom, "@telecom");
        userAccountSuffix.put(OperatorName.Cmcc, "@cmcc");
        userAccountSuffix.put(OperatorName.Cumt, "");
    }

    public void setIpV4(String ipV4) {
        this.ipV4 = ipV4;
    }

    public void setIpV6(String ipV6) {
        this.ipV6 = ipV6;
    }

    public void setMacAddress(String macAddress) {
        this.macAddress = macAddress;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public void setOperatorName(OperatorName operatorName) {
        this.operatorName = operatorName;
    }

    public CumtNetWorkClientImp(String userName, String passWord, String ipV4, String macAddress, OperatorName operatorName) {
        this.userName = userName;
        this.passWord = passWord;
        this.operatorName = operatorName;
        this.macAddress = macAddress;
        this.ipV4 = ipV4;
    }

    public CumtNetWorkClientImp(String ipV4, String ipV6, String macAddress, String userName, String passWord, OperatorName operatorName) {
        this.ipV4 = ipV4;
        this.ipV6 = ipV6;
        this.macAddress = macAddress;
        this.userName = userName;
        this.passWord = passWord;
        this.operatorName = operatorName;
    }

    public CumtNetWorkClientImp(String userName, String passWord, OperatorName operatorName) {
        this.userName = userName;
        this.passWord = passWord;
        this.operatorName = operatorName;
    }

    @Override
    public boolean login() throws NoSuchOperatorName {
        if(this.operatorName == OperatorName.Unicom){
            return loginUnicom();
        }

        if(this.operatorName == OperatorName.Cmcc){
            return loginCmcc();
        }

        if(this.operatorName == OperatorName.Cumt){
            return loginCumt();
        }

        if(this.operatorName == OperatorName.Telecom){
            return loginTelecom();
        }

        throw new NoSuchOperatorName(this.operatorName + "运营商不存在");
    }

    @Override
    public boolean login(String userName, String passWord, OperatorName operatorName) {
        if(userName == null || passWord == null || operatorName == null){
            throw new IllegalArgumentException();
        }

        // 正则表达式校验参数

        String userAccount = userName + userAccountSuffix.get(operatorName);


        String responseBody = null;
        LoginNetWorkParam loginNetWorkPara = new LoginNetWorkParam(userName, passWord);
        loginNetWorkPara.setWlanUserMac(this.macAddress);
        loginNetWorkPara.setWlanUserIp(this.ipV4);
        loginNetWorkPara.setParamA("login");
        loginNetWorkPara.setUserAccount(userAccount);

        // 发起请求
        try {
            responseBody = sendLoginRequest(loginNetWorkPara);
        } catch (IOException ioException) {
            System.out.println("登录失败");
            ioException.printStackTrace();
        }

        if(responseBody == null){
            return false;
        }

        //根据json判断是否请求成功
        String resultJson = responseBody.substring(1, responseBody.length() - 1);
        LoginStatus loginStatus = JSON.parseObject(resultJson, LoginStatus.class);

        if (isLoginSuccess(loginStatus)) {
            return true;
        }

        return false;
    }

    protected boolean isLoginSuccess(LoginStatus loginStatus){
        if(loginStatus == null){
            return false;
        }

        if (loginStatus.getResult().equals("1")) {
            return true;
        }

        return false;
    }

    // 发起注册请求
    protected String sendRegisterRequest(LogoutNetWorkParam logoutNetWorkParam) throws IOException {
        if(logoutNetWorkParam == null){
            throw new IllegalArgumentException();
        }
        Request.Builder requestBuilder = new Request.Builder().url(this.loginUrl);
        HttpUrl.Builder urlBuilder = HttpUrl.parse(this.loginUrl).newBuilder();
        addLogoutParameter(urlBuilder, logoutNetWorkParam);
        requestBuilder.url(urlBuilder.build());
        Request request = requestBuilder.build();

        try (Response response = httpClient.newCall(request).execute()) {
            if(response.isSuccessful()) {
                return response.body().string();
            }
            return null;
        }
    }


    // 返回登录请求请求体 同步请求
    protected String sendLoginRequest(LoginNetWorkParam loginNetWorkParam) throws IOException {
        if(loginNetWorkParam == null){
            throw new IllegalArgumentException();
        }
        // http://10.2.5.251:801/eportal/?c=Portal&a=login&callback=dr1620011598885&login_method=1&user_account=16184876%40unicom&user_password=147934&wlan_user_ip=10.3.94.242&wlan_user_mac=70c94ef77ec7&wlan_ac_ip=&wlan_ac_name=NAS&jsVersion=3.0&_=1620011583355
        Request.Builder requestBuilder = new Request.Builder().url(this.loginUrl);
        HttpUrl.Builder urlBuilder = HttpUrl.parse(this.loginUrl).newBuilder();
        addParameter(urlBuilder, loginNetWorkParam);
        requestBuilder.url(urlBuilder.build());
        Request request = requestBuilder.build();

        //
        final String[] result = new String[1];
        /*httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace(); // 失败打印日志
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 响应结果处理
                System.out.println(response.body());
                result[0] = response.body().toString();
            }
        });
        return result[0];
        */
        try (Response response = httpClient.newCall(request).execute()) {
            return response.body().string();
        }
    }

    // 维护参数
    private void addParameter(HttpUrl.Builder urlBuilder, LoginNetWorkParam loginNetWorkParam){
        urlBuilder.addQueryParameter("a", loginNetWorkParam.getParamA());
        urlBuilder.addQueryParameter("c", loginNetWorkParam.getParamC());
        urlBuilder.addQueryParameter("callback", loginNetWorkParam.getCallback());
        urlBuilder.addQueryParameter("login_method", loginNetWorkParam.getLoginMethod());
        urlBuilder.addQueryParameter("user_account", loginNetWorkParam.getUserAccount());
        urlBuilder.addQueryParameter("user_password", loginNetWorkParam.getUserPassword());
        urlBuilder.addQueryParameter("wlan_user_ip", loginNetWorkParam.getWlanUserIp());
        urlBuilder.addQueryParameter("wlan_user_mac", loginNetWorkParam.getWlanUserMac());
        urlBuilder.addQueryParameter("wlan_user_ac_name", loginNetWorkParam.getWlanAcName());
        urlBuilder.addQueryParameter("wlan_ac_ip", loginNetWorkParam.getWlanAcIp());
        urlBuilder.addQueryParameter("jsVersion", loginNetWorkParam.getJsVersio());
        urlBuilder.addQueryParameter("_", loginNetWorkParam.getParam_());
    }

    private void addLogoutParameter(HttpUrl.Builder urlBuilder, LogoutNetWorkParam logoutNetWorkParam){
        addParameter(urlBuilder, logoutNetWorkParam);
        urlBuilder.addQueryParameter("wlan_user_ipv6",logoutNetWorkParam.getWlanUserIpv6());
        urlBuilder.addQueryParameter("wlan_vlan_id", logoutNetWorkParam.getWlanVlanId());
        urlBuilder.addQueryParameter("ac_logout", logoutNetWorkParam.getAcLogout());
    }

    @Override
    public boolean loginCumt() {
        return login(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean loginTelecom() {
        return login(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean loginCmcc() {
        return login(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean loginUnicom() {
        return login(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean logout() throws NoSuchOperatorName, ResultException {
        if(this.operatorName == OperatorName.Unicom){
            return logoutUnicom();
        }

        if(this.operatorName == OperatorName.Cmcc){
            return logoutCmcc();
        }

        if(this.operatorName == OperatorName.Cumt){
            return logoutCumt();
        }

        if(this.operatorName == OperatorName.Telecom){
            return logoutTelecom();
        }

        throw new NoSuchOperatorName(this.operatorName + "运营商不存在");
    }

    @Override
    public boolean logout(String userName, String passWord, OperatorName operatorName) throws ResultException {
        if(userName == null || passWord == null || operatorName == null){
            throw new IllegalArgumentException();
        }

        String responseBody = null;

        LogoutNetWorkParam logoutNetWorkParam = new LogoutNetWorkParam("drcom", "123");
        logoutNetWorkParam.setWlanUserMac(this.macAddress);
        logoutNetWorkParam.setWlanUserIp(this.ipV4);
        logoutNetWorkParam.setParamA("logout");
        logoutNetWorkParam.setAcLogout("0");
        logoutNetWorkParam.setWlanUserIpv6("");
        logoutNetWorkParam.setWlanVlanId("0");
        logoutNetWorkParam.setWlanUserMac("000000000000");
        logoutNetWorkParam.setWlanAcName("");


        // 发起请求
        try {
            responseBody = sendRegisterRequest(logoutNetWorkParam);
        } catch (IOException ioException) {
            System.out.println("登录失败");
            ioException.printStackTrace();
        }

        if(responseBody == null){
            return false;
        }

        //根据json判断是否请求成功
        LogoutStatus logoutStatus = null;
        try {
            String resultJson = responseBody.substring(1, responseBody.length() - 1);
            logoutStatus = JSON.parseObject(resultJson, LogoutStatus.class);
        } catch (Exception ex){
            throw new ResultException("Json解析异常, 返回参数改变", ex);
        }


        if(isLogoutSuccess(logoutStatus)){
            return true;
        }

        return false;
    }

    private boolean isLogoutSuccess(LogoutStatus logoutStatus){
        if(logoutStatus == null){
            return  false;
        }

        if(logoutStatus.getResult().equals("1")){
            return true;
        }
        return false;

    }

    @Override
    public boolean logoutCumt() throws ResultException {
        return logout(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean logoutUnicom() throws ResultException {
        return logout(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean logoutTelecom() throws ResultException {
        return logout(this.userName, this.passWord, this.operatorName);
    }

    @Override
    public boolean logoutCmcc() throws ResultException {
        return logout(this.userName, this.passWord, this.operatorName);
    }
}
